package com.timedomain.him.remake.core;


import android.content.Context;

import com.timedomain.him.remake.Program;
import com.timedomain.him.remake.service.PlayerService;
import com.timedomain.him.remake.utils.AppSettings;
import com.timedomain.him.remake.utils.FileUtils;
import com.timedomain.him.remake.utils.HLog;
import com.timedomain.him.remake.utils.TimeUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

// 晚安模式
public class NightMode extends BasePlayer implements AutoStopable {

    Timer tickTimer = null;

    private Set<String> ignoredStories;

    private int storyCount = 3;
    private int durationInMinute = 30;

    private Context ctx;

    public NightMode(Context ctx,Set<String> ignoredStories,int storyCount,int minute){
        this.ctx = ctx;
        this.ignoredStories = ignoredStories;
        if(minute < 15){
            minute = 15;
        }
        if(minute > 60){
            minute = 60;
        }
        if(storyCount < 2){storyCount = 2;}
        if(storyCount > 5){storyCount = 5;}

        this.storyCount = storyCount;
        this.durationInMinute = minute;
        constructNightModeSequences(false);
    }

    List<String> nightModeSequences = new ArrayList<>();

    private void constructNightModeSequences(boolean isReWake){
        nightModeSequences.clear();
        if(isReWake){
            nightModeSequences.add(FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","rewake"))); // 重新唤醒后的语音
        }
        else{
            nightModeSequences.add(FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","opening"))); // 开场白
        }
        nightModeSequences.add(FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","before"))); // 你想听故事吗


        List<String> stories = FileUtils.getAllNightStories();
        for (String ignoredOnes :
                ignoredStories) {
            stories.remove(ignoredOnes);
        }

        List<String> shuffedStories = new ArrayList<>();
        while (shuffedStories.size() < 5){
            shuffedStories.addAll(stories);
        }
        Collections.shuffle(shuffedStories); // 打乱故事顺序

        nightModeSequences.add(shuffedStories.get(0));

        for (int i = 1; i < storyCount; i++) {
            nightModeSequences.add(FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","intersection"))); //幕间

            nightModeSequences.add(shuffedStories.get(i)); // 每个故事
        }
        nightModeSequences.add(FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","ending")));// 结尾问候
        nightModeSequences.add(FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","sfx"))); // 翻书声


        for (String oneSeq:nightModeSequences) {
            HLog.i("NightMode", "constructNightModeSequences: "+oneSeq);
        }

    }

    private SimplePlayer currentPlayer = null;

    public void wakeUp(){
        if(!isFallAsleep){return;}
        isFallAsleep = false;
        lastIsFallAsleep = false;
        constructNightModeSequences(true);
        if(currentPlayer != null){
            currentPlayer.close();
        }
        currentPlayer = null;
        started = false;
        start();
    }

    boolean isFallAsleep = false;
    long beginTime = -1;

    public boolean isFallAsleep(){
        return isFallAsleep;
    }

    public boolean isPhoneCharging = false;

    private boolean started = false;
    @Override
    public void start() {
        if(started == false){

            sequencePointer = -1;
            started = true;
            beginTime = TimeUtils.getTimeStampIgnoreTimeZone();

            if(tickTimer != null) {
                tickTimer.cancel();
                tickTimer = null;
            }
            tickTimer = new Timer();

            tickTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    onTick();
                }
            },100L,1000L);
        }
    }

    public void setCurrentMinute(int minute){

        beginTime = TimeUtils.getTimeStampIgnoreTimeZone() - (this.durationInMinute - (minute)) * 60000;
    }

    public int getCurrentMinutes(){
        return (int) ((getRemainTime()+59000) / 60000);
    }

    public long getRemainTime(){
        return durationInMinute * 60000L + beginTime - TimeUtils.getTimeStampIgnoreTimeZone();
    }

    int sequencePointer = -1;

    private boolean lastIsFallAsleep = false;


    /*
    晚安模式过程

    开场白（一般以 “闭上眼睛吧”结尾） （如果是重新唤醒，这里就换成唤醒的语音）
    故事前（我来，讲个故事给你听）
    故事
    幕间（还不困吗）
    故事
    幕间（还醒着呀）
    故事
    结尾（仅翻书声+偶尔的语音）

    晚安模式倒计时结束后会循环播放一个呼吸声

    --------- 以上是原版的过程 -----------

    来点自己的想法

    开场白（一般以 “闭上眼睛吧”结尾） （如果是重新唤醒，这里就换成唤醒的语音）
    故事前（我来，讲个故事给你听）
    故事
    幕间（还不困吗）
    ...(可以从2-5个自选)
    故事
    结尾（仅翻书声+偶尔的语音）
    翻书声循环（偶尔的语音容易在迷迷糊糊时被惊醒）

    晚安模式倒计时结束后会循环播放一个呼吸声

    */

    private void onTick(){
        if(currentPlayer == null || currentPlayer.isStopped()){
            if(currentPlayer!= null){currentPlayer.close();}
            sequencePointer++;
            if(sequencePointer >= nightModeSequences.size()){
                sequencePointer = nightModeSequences.size() - 1;
            }
            currentPlayer = new SimplePlayer(ChannelCreator.FromFile(ctx,nightModeSequences.get(sequencePointer)));
            currentPlayer.setVolume(globalVolume);
            currentPlayer.start();
            HLog.d("NightMode", "onTick: Current = "+nightModeSequences.get(sequencePointer));
            if(sequencePointer == nightModeSequences.size()-1){
                currentPlayer.setLooping(true);

                HLog.d("NightMode", "onTick: SetLooping for "+nightModeSequences.get(sequencePointer));
            }
        }
        this.isFallAsleep = getRemainTime() <=0;
        if(lastIsFallAsleep != isFallAsleep && isFallAsleep == true){
            currentPlayer.close();
            currentPlayer = null;
            currentPlayer = new SimplePlayer(ChannelCreator.FromFile(ctx,FileUtils.pickRandomOneOgg(FileUtils.pathCombine("night","sleeping"))));
            currentPlayer.start();
            currentPlayer.setLooping(true);
            setVolume(AppSettings.nightModeVolumeAdjustment);
            lastIsFallAsleep = isFallAsleep;
        }
        if(getRemainTime() < 15000 && getRemainTime() > 2000){
            setVolume(getVolume() / 13000f * (getRemainTime() - 2000f));
        }
        else if(getRemainTime() > 15000){
            setVolume(1.0f);
        }
    }

    @Override
    public float getPeak() {

        float amp = currentPlayer == null ? 0 : currentPlayer.getPeak();
        if(isFallAsleep){
            return amp * 3 * 0.7f;
        }
        else{
            return amp * globalVolume;
        }
    }

    @Override
    public void stop() {
        if(currentPlayer != null){
            currentPlayer.stop();
        }
        if(tickTimer != null){

            tickTimer.cancel();
        }
        tickTimer = null;
    }


    @Override
    public void pause() {
        if(currentPlayer != null){
            currentPlayer.pause();
        }
    }

    @Override
    public void close() {
        if(tickTimer != null){
            tickTimer.cancel();
        }
        if(currentPlayer != null){
            currentPlayer.stop();
        }
    }

    @Override
    public boolean isPlaying() {
        return true;
    }

    @Override
    public long getDuration() {
        return currentPlayer == null ? 1 : currentPlayer.getDuration();
    }

    @Override
    public long getPosition() {
        return currentPlayer == null ? 0 : currentPlayer.getPosition();
    }

    @Override
    public boolean isStopped() {
        return false;
    }

    private float globalVolume = 1;

    @Override
    public void setVolume(float volume) {
        globalVolume = volume;
        if(currentPlayer != null){currentPlayer.setVolume(volume);};
    }

    @Override
    public float getVolume() {
        return globalVolume;
    }

    @Override
    public void setPosition(long pos) {
        if(currentPlayer != null){
            currentPlayer.setPosition(pos);
        }
    }

    @Override
    public boolean shouldStop() {
        if(AppSettings.nightModeIgnoreBattery){return false;}
        return (!isPhoneCharging) ?  (getCurrentMinutes() < -45) : (getCurrentMinutes() < -500);
    }
}
